package com.cheche.dn.error;

import com.cheche.dn.Result;
import com.cheche.dn.utils.JsonUtil;
import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;

import javax.servlet.http.HttpServletRequest;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Map;

/**
 * System Error Handler
 * Created by cheshun on 15/5/8.
 */
@ControllerAdvice(annotations = {RestController.class})
public class ExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(ExceptionHandler.class);

    /**
     * Handle exceptions thrown by handlers.
     */
    @org.springframework.web.bind.annotation.ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public Object exception(Exception exception, WebRequest webRequest) {
        HttpServletRequest request = ((ServletWebRequest) webRequest).getRequest();
        Throwable throwable = Throwables.getRootCause(exception);

        Map<String, Object> header = Maps.newHashMap();
        Enumeration<String> keys = request.getHeaderNames();
        while (keys.hasMoreElements()) {
            String key = keys.nextElement();
            header.put(key, request.getHeader(key));
        }

        String requestUri = request.getRequestURI();

        String exceptionMessage = String.format("ExceptionInfo: \nStatusCode->( %d )\nUrl->( %s )\nMethod->( %s )\nParameter->( %s )\nHeader->( %s )",
                HttpStatus.INTERNAL_SERVER_ERROR.value(), requestUri, request.getMethod(), JsonUtil.toJson(request.getParameterMap()), JsonUtil.toJson(header));

        logger.error(exceptionMessage, throwable);

        String errorMessage = HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase();
        if (throwable instanceof MissingServletRequestParameterException) {
            errorMessage = throwable.getMessage();
        }

        String message = MessageFormat.format("Http code {0} returned for {1} with message {2}.",
                HttpStatus.INTERNAL_SERVER_ERROR.value(), requestUri, errorMessage);

        return Result.error(ErrorCode.ERROR, message);
    }
}
